package jannex.internal;

import jannex.Jannex;
import jannex.JannexException;
import jannex.label.LabelMap;
import jannex.mapping.ResultSetHandler;
import jannex.sql.*;
import jannex.sql.extensions.TypedResultSetImpl;

import java.io.InputStream;
import java.io.Reader;
import java.io.Serializable;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.*;
import java.sql.Date;
import java.util.*;

// TODO probably needs builder, and more options for MetaData
// TODO should support more rows?
public class ResultRow extends AbstractMap<String, Object> implements Serializable, JxResultSet {

	private final Object[] data;
	private final String[] labels;
    private final String[] tables;

    private boolean nextOnce = false;

    private transient Map<String, Object> map;
    private transient Jannex jannex = Jannex.STANDALONE;

	public ResultRow(Object[] data, String[] labels, String[] tables) {
        this(Jannex.STANDALONE, data, labels, tables);
	}

    public ResultRow(Jannex jannex, Object[] data, String[] labels, String[] tables) {
        this.jannex = jannex;
        this.data = data;
        this.labels = labels;
        this.tables = tables;
    }

    private Map<String, Object> asMap() {
        if (map == null) {
            LabelMap.Builder<Object> builder = LabelMap.builder(labels.length);
            for (int i = 0; i < labels.length; i++) {
                builder.put(labels[i], data[i]);
            }
            map = builder.build();
        }
        return map;
    }

    @Override
    public <E> TypedResultSet<E> as(Class<E> elementClass) throws JannexException {
        return new TypedResultSetImpl<>(this, jannex, jannex.getHandler(elementClass));
    }

    @Override
    public <E> TypedResultSet<E> as(ResultSetHandler<E> handler) throws JannexException {
        return new TypedResultSetImpl<>(this, jannex, handler);
    }

    @Override
    public <E> Fetcher<E> fetch(Class<E> elementClass) throws JannexException {
        return as(elementClass).fetch();
    }

    @Override
    public JxResultSet subSetFromTable(String tableName) {
        return ResultSubSet.forTableName(this, jannex, tableName);
    }

    @Override
    public JxResultSet subSetFrom(int... columnIndexes) {
        return ResultSubSet.forColumnIndexes(this, jannex, columnIndexes);
    }

    @Override
    public boolean next() throws JannexException {
        if (!nextOnce) {
            nextOnce = true;
            return true;
        }
        return false;
    }

    @Override
    public void close() throws JannexException {
    }

    @Override
    public boolean wasNull() throws JannexException {
        return false;
    }

    @Override
    public String getString(int columnIndex) throws JannexException {
        return ReflectionUtils.cast(getObject(columnIndex));
    }

    @Override
    public boolean getBoolean(int columnIndex) throws JannexException {
        return ReflectionUtils.castBoolean(getObject(columnIndex));
    }

    @Override
    public byte getByte(int columnIndex) throws JannexException {
        return ReflectionUtils.castByte(getObject(columnIndex));
    }

    @Override
    public short getShort(int columnIndex) throws JannexException {
        return ReflectionUtils.castShort(getObject(columnIndex));
    }

    @Override
    public int getInt(int columnIndex) throws JannexException {
        return ReflectionUtils.castInt(getObject(columnIndex));
    }

    @Override
    public long getLong(int columnIndex) throws JannexException {
        return ReflectionUtils.castLong(getObject(columnIndex));
    }

    @Override
    public float getFloat(int columnIndex) throws JannexException {
        return ReflectionUtils.castFloat(getObject(columnIndex));
    }

    @Override
    public double getDouble(int columnIndex) throws JannexException {
        return ReflectionUtils.castDouble(getObject(columnIndex));
    }

    @Override
    @Deprecated
    @SuppressWarnings("deprecation")
    public BigDecimal getBigDecimal(int columnIndex, int scale) throws JannexException {
        return getBigDecimal(columnIndex).setScale(scale);
    }

    @Override
    public byte[] getBytes(int columnIndex) throws JannexException {
        return ReflectionUtils.castByteArray(getObject(columnIndex));
    }

    @Override
    public Date getDate(int columnIndex) throws JannexException {
        return ReflectionUtils.cast(getObject(columnIndex));
    }

    @Override
    public Time getTime(int columnIndex) throws JannexException {
        return ReflectionUtils.cast(getObject(columnIndex));
    }

    @Override
    public Timestamp getTimestamp(int columnIndex) throws JannexException {
        return ReflectionUtils.cast(getObject(columnIndex));
    }

    @Override
    public InputStream getAsciiStream(int columnIndex) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot manipulate streams from ResultRow");
    }

    @Override
    @Deprecated
    @SuppressWarnings("deprecation")
    public InputStream getUnicodeStream(int columnIndex) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot manipulate streams from ResultRow");
    }

    @Override
    public InputStream getBinaryStream(int columnIndex) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot manipulate streams from ResultRow");
    }

    @Override
    public String getString(String columnLabel) throws JannexException {
        return ReflectionUtils.cast(getObject(columnLabel));
    }

    @Override
    public boolean getBoolean(String columnLabel) throws JannexException {
        return ReflectionUtils.castBoolean(getObject(columnLabel));
    }

    @Override
    public byte getByte(String columnLabel) throws JannexException {
        return ReflectionUtils.castByte(getObject(columnLabel));
    }

    @Override
    public short getShort(String columnLabel) throws JannexException {
        return ReflectionUtils.castShort(getObject(columnLabel));
    }

    @Override
    public int getInt(String columnLabel) throws JannexException {
        return ReflectionUtils.castInt(getObject(columnLabel));
    }

    @Override
    public long getLong(String columnLabel) throws JannexException {
        return ReflectionUtils.castLong(getObject(columnLabel));
    }

    @Override
    public float getFloat(String columnLabel) throws JannexException {
        return ReflectionUtils.castFloat(getObject(columnLabel));
    }

    @Override
    public double getDouble(String columnLabel) throws JannexException {
        return ReflectionUtils.castDouble(getObject(columnLabel));
    }

    @Override
    @Deprecated
    @SuppressWarnings("deprecation")
    public BigDecimal getBigDecimal(String columnLabel, int scale) throws JannexException {
        return getBigDecimal(columnLabel).setScale(scale);
    }

    @Override
    public byte[] getBytes(String columnLabel) throws JannexException {
        return ReflectionUtils.castByteArray(getObject(columnLabel));
    }

    @Override
    public Date getDate(String columnLabel) throws JannexException {
        return ReflectionUtils.cast(getObject(columnLabel));
    }

    @Override
    public Time getTime(String columnLabel) throws JannexException {
        return ReflectionUtils.cast(getObject(columnLabel));
    }

    @Override
    public Timestamp getTimestamp(String columnLabel) throws JannexException {
        return ReflectionUtils.cast(getObject(columnLabel));
    }

    @Override
    public InputStream getAsciiStream(String columnLabel) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot manipulate streams from ResultRow");
    }

    @Override
    @Deprecated
    @SuppressWarnings("deprecation")
    public InputStream getUnicodeStream(String columnLabel) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot manipulate streams from ResultRow");
    }

    @Override
    public InputStream getBinaryStream(String columnLabel) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot manipulate streams from ResultRow");
    }

    @Override
    public SQLWarning getWarnings() throws JannexException {
        return null;
    }

    @Override
    public void clearWarnings() throws JannexException {
    }

    @Override
    public String getCursorName() throws JannexException {
        return null;
    }

    @Override
    public JxResultSetMetaData getMetaData() throws JannexException {
        return new ResultRowMetaData(this, labels, tables);
    }

    @Override
    public Object getObject(int columnIndex) throws JannexException {
        return data[columnIndex-1];
    }

    @Override
    public Object getObject(String columnLabel) throws JannexException {
        return asMap().get(columnLabel);
    }

    @Override
    public int findColumn(String columnLabel) throws JannexException {
        return 0;
    }

    @Override
    public Reader getCharacterStream(int columnIndex) throws JannexException {
        return null;
    }

    @Override
    public Reader getCharacterStream(String columnLabel) throws JannexException {
        return null;
    }

    @Override
    public BigDecimal getBigDecimal(int columnIndex) throws JannexException {
        return ReflectionUtils.cast(getObject(columnIndex));
    }

    @Override
    public BigDecimal getBigDecimal(String columnLabel) throws JannexException {
        return ReflectionUtils.cast(getObject(columnLabel));
    }

    @Override
    public boolean isBeforeFirst() throws JannexException {
        return !nextOnce;
    }

    @Override
    public boolean isAfterLast() throws JannexException {
        return nextOnce;
    }

    @Override
    public boolean isFirst() throws JannexException {
        return true;
    }

    @Override
    public boolean isLast() throws JannexException {
        return true;
    }

    @Override
    public void beforeFirst() throws JannexException {
        nextOnce = false;
    }

    @Override
    public void afterLast() throws JannexException {
        nextOnce = true;
    }

    @Override
    public boolean first() throws JannexException {
        nextOnce = false;
        return true;
    }

    @Override
    public boolean last() throws JannexException {
        return first();
    }

    @Override
    public int getRow() throws JannexException {
        return isBeforeFirst() ? 0 : 1;
    }

    @Override
    public boolean absolute(int row) throws JannexException {
        return false;
    }

    @Override
    public boolean relative(int rows) throws JannexException {
        return false;
    }

    @Override
    public boolean previous() throws JannexException {
        return isAfterLast() && first();
    }

    @Override
    public void setFetchDirection(int direction) throws JannexException {
    }

    @Override
    public int getFetchDirection() throws JannexException {
        return ResultSet.FETCH_FORWARD;
    }

    @Override
    public void setFetchSize(int rows) throws JannexException {
    }

    @Override
    public int getFetchSize() throws JannexException {
        return 1;
    }

    @Override
    public int getType() throws JannexException {
        return ResultSet.TYPE_FORWARD_ONLY;
    }

    @Override
    public int getConcurrency() throws JannexException {
        return ResultSet.CONCUR_READ_ONLY;
    }

    @Override
    public boolean rowUpdated() throws JannexException {
        return false;
    }

    @Override
    public boolean rowInserted() throws JannexException {
        return false;
    }

    @Override
    public boolean rowDeleted() throws JannexException {
        return false;
    }

    @Override
    public void updateNull(int columnIndex) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateBoolean(int columnIndex, boolean x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateByte(int columnIndex, byte x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateShort(int columnIndex, short x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateInt(int columnIndex, int x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateLong(int columnIndex, long x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateFloat(int columnIndex, float x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateDouble(int columnIndex, double x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateBigDecimal(int columnIndex, BigDecimal x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateString(int columnIndex, String x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateBytes(int columnIndex, byte[] x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateDate(int columnIndex, Date x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateTime(int columnIndex, Time x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateTimestamp(int columnIndex, Timestamp x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateAsciiStream(int columnIndex, InputStream x, int length) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateBinaryStream(int columnIndex, InputStream x, int length) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateCharacterStream(int columnIndex, Reader x, int length) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateObject(int columnIndex, Object x, int scaleOrLength) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateObject(int columnIndex, Object x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateNull(String columnLabel) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateBoolean(String columnLabel, boolean x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateByte(String columnLabel, byte x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateShort(String columnLabel, short x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateInt(String columnLabel, int x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateLong(String columnLabel, long x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateFloat(String columnLabel, float x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateDouble(String columnLabel, double x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateBigDecimal(String columnLabel, BigDecimal x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateString(String columnLabel, String x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateBytes(String columnLabel, byte[] x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateDate(String columnLabel, Date x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateTime(String columnLabel, Time x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateTimestamp(String columnLabel, Timestamp x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateAsciiStream(String columnLabel, InputStream x, int length) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateBinaryStream(String columnLabel, InputStream x, int length) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateCharacterStream(String columnLabel, Reader reader, int length) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateObject(String columnLabel, Object x, int scaleOrLength) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateObject(String columnLabel, Object x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void insertRow() throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateRow() throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void deleteRow() throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void refreshRow() throws JannexException {
    }

    @Override
    public void cancelRowUpdates() throws JannexException {
    }

    @Override
    public void moveToInsertRow() throws JannexException {
    }

    @Override
    public void moveToCurrentRow() throws JannexException {
    }

    @Override
    public JxStatement getStatement() throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot get Statement from ResultRow");
    }

    @Override
    public Object getObject(int columnIndex, Map<String, Class<?>> map) throws JannexException {
        return getObject(columnIndex);
    }

    @Override
    public JxRef getRef(int columnIndex) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot get Ref from ResultRow");
    }

    @Override
    public JxBlob getBlob(int columnIndex) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot get Blob from ResultRow");
    }

    @Override
    public JxClob getClob(int columnIndex) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot get Clob from ResultRow");
    }

    @Override
    public JxArray getArray(int columnIndex) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot get array from ResultRow");
    }

    @Override
    public Object getObject(String columnLabel, Map<String, Class<?>> map) throws JannexException {
        return getObject(columnLabel);
    }

    @Override
    public JxRef getRef(String columnLabel) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot get Ref from ResultRow");
    }

    @Override
    public JxBlob getBlob(String columnLabel) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot get Blob from ResultRow");
    }

    @Override
    public JxClob getClob(String columnLabel) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot get Clob from ResultRow");
    }

    @Override
    public JxArray getArray(String columnLabel) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot get Array from ResultRow");
    }

    @Override
    public Date getDate(int columnIndex, Calendar cal) throws JannexException {
        return ReflectionUtils.cast(getObject(columnIndex));
    }

    @Override
    public Date getDate(String columnLabel, Calendar cal) throws JannexException {
        return ReflectionUtils.cast(getObject(columnLabel));
    }

    @Override
    public Time getTime(int columnIndex, Calendar cal) throws JannexException {
        return ReflectionUtils.cast(getObject(columnIndex));
    }

    @Override
    public Time getTime(String columnLabel, Calendar cal) throws JannexException {
        return ReflectionUtils.cast(getObject(columnLabel));
    }

    @Override
    public Timestamp getTimestamp(int columnIndex, Calendar cal) throws JannexException {
        return ReflectionUtils.cast(getObject(columnIndex));
    }

    @Override
    public Timestamp getTimestamp(String columnLabel, Calendar cal) throws JannexException {
        return ReflectionUtils.cast(getObject(columnLabel));
    }

    @Override
    public URL getURL(int columnIndex) throws JannexException {
        return ReflectionUtils.cast(getObject(columnIndex));
    }

    @Override
    public URL getURL(String columnLabel) throws JannexException {
        return ReflectionUtils.cast(getObject(columnLabel));
    }

    @Override
    public void updateRef(int columnIndex, Ref x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateRef(String columnLabel, Ref x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateBlob(int columnIndex, Blob x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateBlob(String columnLabel, Blob x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateClob(int columnIndex, Clob x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateClob(String columnLabel, Clob x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateArray(int columnIndex, Array x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateArray(String columnLabel, Array x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public RowId getRowId(int columnIndex) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot get RowId from ResultRow");
    }

    @Override
    public RowId getRowId(String columnLabel) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot get RowId from ResultRow");
    }

    @Override
    public void updateRowId(int columnIndex, RowId x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateRowId(String columnLabel, RowId x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public int getHoldability() throws JannexException {
        return ResultSet.HOLD_CURSORS_OVER_COMMIT;
    }

    @Override
    public boolean isClosed() throws JannexException {
        return false;
    }

    @Override
    public void updateNString(int columnIndex, String nString) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateNString(String columnLabel, String nString) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateNClob(int columnIndex, NClob nClob) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateNClob(String columnLabel, NClob nClob) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public JxNClob getNClob(int columnIndex) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot get NClob from ResultRow");
    }

    @Override
    public JxNClob getNClob(String columnLabel) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot get NClob from ResultRow");
    }

    @Override
    public JxSQLXML getSQLXML(int columnIndex) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot get SQLXML from ResultRow");
    }

    @Override
    public JxSQLXML getSQLXML(String columnLabel) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot get SQLXML from ResultRow");
    }

    @Override
    public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public String getNString(int columnIndex) throws JannexException {
        return getString(columnIndex);
    }

    @Override
    public String getNString(String columnLabel) throws JannexException {
        return getString(columnLabel);
    }

    @Override
    public Reader getNCharacterStream(int columnIndex) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot get Reader from ResultRow");
    }

    @Override
    public Reader getNCharacterStream(String columnLabel) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot get Reader from ResultRow");
    }

    @Override
    public void updateNCharacterStream(int columnIndex, Reader x, long length) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateAsciiStream(int columnIndex, InputStream x, long length) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateBinaryStream(int columnIndex, InputStream x, long length) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateCharacterStream(int columnIndex, Reader x, long length) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateAsciiStream(String columnLabel, InputStream x, long length) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateBinaryStream(String columnLabel, InputStream x, long length) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateCharacterStream(String columnLabel, Reader reader, long length) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateBlob(int columnIndex, InputStream inputStream, long length) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateBlob(String columnLabel, InputStream inputStream, long length) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateClob(int columnIndex, Reader reader, long length) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateClob(String columnLabel, Reader reader, long length) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateNClob(int columnIndex, Reader reader, long length) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateNClob(String columnLabel, Reader reader, long length) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateNCharacterStream(int columnIndex, Reader x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateNCharacterStream(String columnLabel, Reader reader) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateAsciiStream(int columnIndex, InputStream x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateBinaryStream(int columnIndex, InputStream x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateCharacterStream(int columnIndex, Reader x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateAsciiStream(String columnLabel, InputStream x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateBinaryStream(String columnLabel, InputStream x) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateCharacterStream(String columnLabel, Reader reader) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateBlob(int columnIndex, InputStream inputStream) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateBlob(String columnLabel, InputStream inputStream) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateClob(int columnIndex, Reader reader) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateClob(String columnLabel, Reader reader) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateNClob(int columnIndex, Reader reader) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    public void updateNClob(String columnLabel, Reader reader) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot update ResultRow");
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> T getObject(int columnIndex, Class<T> type) throws JannexException {
        return (T) getObject(columnIndex); // TODO should be a little more robust
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> T getObject(String columnLabel, Class<T> type) throws JannexException {
        return (T) getObject(columnLabel);  // TODO should be a little more robust
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws JannexException {
        throw new JxSqlFeatureNotSupportedException("Cannot unwrap ResultRow");
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws JannexException {
        return false;
    }

    @Override
    public int size() {
        return asMap().size();
    }

    @Override
    public boolean containsKey(Object key) {
        return asMap().containsKey(key);
    }

    @Override
    public boolean containsValue(Object value) {
        return asMap().containsValue(value);
    }

    @Override
    public Object get(Object key) {
        return asMap().get(key);
    }

    @Override
    public Set<String> keySet() {
        return asMap().keySet();
    }

    @Override
    public Collection<Object> values() {
        return asMap().values();
    }

    @Override
    public Set<Entry<String, Object>> entrySet() {
        return asMap().entrySet();
    }
}
